﻿using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Microsoft.VisualBasic.CompilerServices;

namespace S3Des
{
    class S3Des
    {
        private static bool decrypting = false;
        private static bool encrypting = false;

        private static string folderPath = "";
        private static string inputFile = "";
        private static string outputFile = "";
        private static string keyString = "";

        public static string[] robustNewlineDelim = new string[] { "\r\n", "\n" };
        public static char[] spaceDelim = new char[] { ' ' };
        public static string ApplicationName = "S3Des v1.0.0.0";

        public static string ENC_KEY_STR = "Li，Zhaoqian@13501380950_$@ 李某-";

        static void Exit(object sender = null, EventArgs e = null)
        {
            Console.ResetColor();
            Environment.Exit(0);
        }

        static void Help(string LanguageCode = "", string command = "")
        {
            string[] zh_CN_Help = {
                "",
                "作用: 加密或者解密3DES文件",
                "",
                "用法: S3Des [-h] [-c] [-d : -e] [-p] Directory [-i] Source [-o] Destination [-k] Secretkey",
                "",
                "命令列表:",
                "  -h\t\t\t帮助",
                "  -c\t\t\t关于",
                "  -d\t\t\t解密",
                "  -e\t\t\t加密",
                "  -p\t\t\t目录文件夹",
                "  -i\t\t\t输入目标",
                "  Source\t\t输入文件",
                "  -o\t\t\t输出目标",
                "  Destination\t\t输出文件",
                "  -k\t\t\t密钥目标",
                "  Secretkey\t\t密钥字符串",
                "",
                "示例:",
                "  查看帮助信息: .//S3Des -h",
                "  查看关于信息: .//S3Des -c",
                "  解密文件并输出: .//S3Des -d -p . -i ContentKey.inf -o ContentKey.csv -k abc123xyz",
                "  加密文件并输出: .//S3Des -e -p . -i ContentKey.csv -o ContentKey.inf -k abc123xyz",
                ""
            };

            string[] en_US_Help = {
                "",
                "Effect: encrypt or decrypt 3DES files",
                "",
                "Usage: S3Des [-h] [-c] [-d : -e] [-p] Directory [-i ] Source [-o] Destination [-k] Secretkey",
                "",
                "List of all commands:",
                "  -h\t\t\tShow the help",
                "  -c\t\t\tShows the credits",
                "  -d\t\t\tDecrypt",
                "  -e\t\t\tEncrypt",
                "  -p\t\t\tDirectory folder",
                "  -i\t\t\tInput target",
                "  Source\t\tinput file",
                "  -o\t\t\tOutput target",
                "  Destination\t\tOutput file",
                "  -k\t\t\tKey target",
                "  Secretkey\t\tKey string",
                "",
                 "Example:",
                "  View help message: .//S3Des -h",
                "  View credits message: .//S3Des -c",
                "  Decrypt the file and output: .//S3Des -d -p . -i ContentKey.inf -o ContentKey.csv -k abc123xyz",
                "  Encrypt the file and output: .//S3Des -e -p . -i ContentKey.csv -o ContentKey.inf -k abc123xyz",
                ""
            };

            if (LanguageCode == "")
            {
                LanguageCode = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
            }

            switch (LanguageCode)
            {
                case "zh-CN":
                    for (int i = 0; i < zh_CN_Help.Length; i++)
                        Console.WriteLine(zh_CN_Help[i]);
                    break;
                case "en_US":
                    for (int i = 0; i < en_US_Help.Length; i++)
                        Console.WriteLine(en_US_Help[i]);
                    break;
                default:
                    for (int i = 0; i < en_US_Help.Length; i++)
                        Console.WriteLine(en_US_Help[i]);
                    break;
            }
        }

        public static bool DecSaveFile(string folderPath, string inputFile, string outputFile, string keyString)
        {
            bool result = true;
            try
            {
                StreamReader streamReader = new StreamReader(folderPath + inputFile, Encoding.UTF8);
                string encryptedtext = streamReader.ReadToEnd();
                streamReader.Close();

                Simple3Des simple3Des = new Simple3Des(keyString);
                string decryptedtext = simple3Des.DecryptData(encryptedtext);

                StreamWriter streamWriter = new StreamWriter(folderPath + outputFile, false, Encoding.UTF8);
                streamWriter.Write(decryptedtext);
                streamWriter.Flush();
                streamWriter.Close();

                result = true;
            }
            catch (Exception ex)
            {
                string message = ex.Message;
                result = false;
            }

            return result;
        }

        public static bool EncSaveFile(string folderPath, string inputFile, string outputFile, string keyString)
        {
            bool result = true;
            try
            {
                StreamReader streamReader = new StreamReader(folderPath + inputFile, Encoding.UTF8);
                string decryptedtext = streamReader.ReadToEnd();
                streamReader.Close();

                Simple3Des simple3Des = new Simple3Des(keyString);
                string encryptedtext = simple3Des.EncryptData(decryptedtext);

                StreamWriter streamWriter = new StreamWriter(folderPath + outputFile, false, Encoding.UTF8);
                streamWriter.Write(encryptedtext);
                streamWriter.Flush();
                streamWriter.Close();

                result = true;
            }
            catch (Exception ex)
            {
                string message = ex.Message;
                result = false;
            }

            return result;
        }

        static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.Title = ApplicationName;

            if (args.Length == 0)
            {
                Console.WriteLine("Warning: No arguments present.");
                Help();
                Exit();
            }

            for (int i = 0; i < args.Count(); i++)
            {
                switch (args[i].ToLower())
                {
                    case "/?":
                    case "-h":
                        Help();
                        Exit();
                        break;
                    case "-c":
                        Console.WriteLine("");
                        Console.WriteLine("encrypt or decrypt 3DES files");
                        Console.WriteLine("");
                        Console.WriteLine("For testing use only");
                        Console.WriteLine("The author is not responsible");
                        Console.WriteLine("");
                        Console.WriteLine("Auther: lsgxeva");
                        Console.WriteLine("Email: lsgxthink@163.com");
                        Console.WriteLine("HomePage: https://gitee.com/lsgx");
                        Console.WriteLine("");
                        Exit();
                        break;
                    case "-d":
                        decrypting = true;
                        break;
                    case "-e":
                        encrypting = true;
                        break;
                    case "-p":
                        folderPath = args[i + 1] + "\\";
                        break;
                    case "-i":
                        inputFile = args[i + 1];
                        break;
                    case "-o":
                        outputFile = args[i + 1];
                        break;
                    case "-k":
                        keyString = args[i + 1];
                        break;
                }
            }

            if (decrypting && encrypting)
            {
                Console.WriteLine("Error: Can't perform encryption and decryption at the same time.");
                Exit();
            }

            if (!(decrypting || encrypting))
            {
                Console.WriteLine("Error: encryption or decryption parameters must be set. ( [-d : -e] )");
                Exit();
            }

            if (!(folderPath != "" && inputFile != "" && outputFile != ""))
            {
                Console.WriteLine("Error: These parameters must be set at the same time. ( [-p] Directory [-i ] Source [-o] Destination ) ");
                Exit();
            }

            if (keyString == "")
            {
                keyString = ENC_KEY_STR;
            }

            if (decrypting)
            {
                bool result = DecSaveFile(folderPath, inputFile, outputFile, keyString);
                if (result)
                {
                    Console.WriteLine("Information: Successfully to decrypted " + folderPath + inputFile + " as " + folderPath + outputFile);
                }
                else
                {
                    Console.WriteLine("Warning: Failed to decrypted " + folderPath + inputFile + " as " + folderPath + outputFile);
                }
                Exit();
            }

            if (encrypting)
            {
                bool result = EncSaveFile(folderPath, inputFile, outputFile, keyString);
                if (result)
                {
                    Console.WriteLine("Information: Successfully to encrypted " + folderPath + inputFile + " as " + folderPath + outputFile);
                }
                else
                {
                    Console.WriteLine("Warning: Failed to encrypted " + folderPath + inputFile + " as " + folderPath + outputFile);
                }
                Exit();
            }

            Exit(null, null);
        }
    }
    
    // Token: 0x02000049 RID: 73
    public sealed class Simple3Des
    {
        // Token: 0x06000299 RID: 665 RVA: 0x000207CC File Offset: 0x0001E9CC
        private byte[] TruncateHash(string key, int length)
        {
            SHA1CryptoServiceProvider sha1CryptoServiceProvider = new SHA1CryptoServiceProvider();
            byte[] bytes = Encoding.UTF8.GetBytes(key);
            byte[] array = sha1CryptoServiceProvider.ComputeHash(bytes);
            return (byte[])Utils.CopyArray((Array)array, new byte[checked(length - 1 + 1)]);
        }

        // Token: 0x0600029A RID: 666 RVA: 0x00020814 File Offset: 0x0001EA14
        public Simple3Des(string key)
        {
            this.TripleDes = new TripleDESCryptoServiceProvider();
            this.TripleDes.Key = this.TruncateHash(key, this.TripleDes.KeySize / 8);
            this.TripleDes.IV = this.TruncateHash("", this.TripleDes.BlockSize / 8);
        }

        // Token: 0x0600029B RID: 667 RVA: 0x0002087C File Offset: 0x0001EA7C
        public string EncryptData(string plaintext)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(plaintext);
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, this.TripleDes.CreateEncryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(bytes, 0, bytes.Length);
            cryptoStream.FlushFinalBlock();
            return Convert.ToBase64String(memoryStream.ToArray());
        }

        // Token: 0x0600029C RID: 668 RVA: 0x000208D4 File Offset: 0x0001EAD4
        public string DecryptData(string encryptedtext)
        {
            byte[] array = Convert.FromBase64String(encryptedtext);
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, this.TripleDes.CreateDecryptor(), CryptoStreamMode.Write);
            cryptoStream.Write(array, 0, array.Length);
            cryptoStream.FlushFinalBlock();
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }

        // Token: 0x04000367 RID: 871
        private TripleDESCryptoServiceProvider TripleDes;
    }

}
